今天一樣是 jinja 的內容,會講到模板的繼承。這個在網頁有固定排版或是格式的時候很好用,不用一直重複複製貼上。就算網頁沒有固定排版,基本上 head、要引入的 CSS、JS 也可能有重複。簡單來說,我覺得這是一個一定會用到的功能,後面開始寫專案的時候也會用到。
先來看個範例。base.html
和 index.html
都必須放在 templates/
裡面。
app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index_page():
user = "Cat"
return render_template("index.html", user=user)
app.run(host="127.0.0.1", port=8080, debug=True)
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<nav>
nav
</nav>
<main>
{% block content %}
{% endblock %}
</main>
<footer>
footer
</footer>
</body>
index.html
{% extends "base.html" %}
{% block title %}Index Page{% endblock %}
{% block content %}
<p>
{{ user }}
</p>
{% endblock %}
app.py
和之前差不多,就把 user
傳入 jinja 處理。
base.html
裡面出現了 {% block %}
,他代表這是一個可以自由發揮的區塊,也就是非排版的部分,而 block
後面接的 title
和 content
則是這個 block 的名稱。我們在 base.html
定義好一些區塊,然後交給其他模板去寫,以此處為例就是下面的 index.html
。
最後我們看到 index.html
,他在最一開始就宣告說這個模板是從 base.html
繼承來的,所以他會照著剛剛 base.html
的格式生成已經寫好的內容。接下來,我們把剛剛在 base.html
留下來的 block 一一填好。首先是 title
,就跟剛剛的寫法一樣,需要 {% block title %}{% endblock %}
,但這次中間需要放入自己想要的網站標題,此處就用 Index Page
為例。下一個是 content
,在這邊我們就把 flask 傳過來的 user
塞進去。這樣就完成了樣板的繼承,這時候打開瀏覽器應該可以看到它顯示出 nav
、剛剛傳入的 user
、footer
。
最後我們來實作未來要用到的 base.html
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
{% block extra_import %}
{% endblock %}
</head>
<body>
<nav>
<!-- unauthorized -->
<span><a href="/login">Login</a></span>
<span><a href="/register">Register</a></span>
<!-- normal user -->
<span><a href="/dashboard">Dashboard</a></span>
<span><a href="/posts">All posts</a></span>
<span><a href="/post/add">Add post</a></span>
<span><a href="/setting">Setting</a></span>
<!-- admin -->
<span><a href="/admin_dashboard/posts">Admin Dashboard for posts</a></span>
<span><a href="/admin_dashboard/comments">Admin Dashboard for comments</a></span>
<span><a href="/manage_user">Manage User</a></span>
</nav>
<main>
{{ display_msg(get_flashed_messages(with_categories=True)) }}
{% block content %}
{% endblock %}
</main>
<footer>
© siriuskoan
</footer>
</body>
</html>
這裡多數都是跟剛剛差不多的內容,比較特別的是我多放了一個 extra_import
,在這裡可以放一些 CSS、JS 等等的,而他們要放在哪裡則是明天的主題。
在 nav
的部分我放了很多連結,同時也幫他們上了註解,很明顯我們不可能對所有人都顯示出一樣的 nav
,所以在未來我們會在這裡做一些判斷來決定到底要怎麼顯示 nav
。
有了這個模板之後,我們未來所有的 HTML 都會繼承自他,可以大幅減少重複的內容。